﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include "GbmpUiPlatform.h"
#include "IActionDrawRectBehavior.h"

namespace gcmp
{
    class IDocument;
    class IUiView;
    class IPropertyPanelEventArgs;
    class IGraphicsElementShape;
    class ISnap;

    struct  DefineInputDialogParams
    {
        std::wstring title;
        std::vector<OwnerPtr<IControlDefinition>> inputItems;
    };

    class GBMP_UI_PLATFORM_EXPORT DrawRectElementBehavior : public IActionDrawRectBehavior
    {
        CANNOT_COPY_OR_ASSIGN(DrawRectElementBehavior)
    public:
        DrawRectElementBehavior(IDocument* pDoc);
        virtual ~DrawRectElementBehavior();

        typedef std::function<bool(IUiView* pCurrentView)> OnInitActionCallback;
        template<typename T>
        static OnInitActionCallback CreateOnInitActionCallback(
            bool(T::*func)(IUiView* pCurrentView), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnInitActionCallback(OnInitActionCallback callback);

        typedef std::function<bool()> OnDestroyActionCallback;
        template<typename T>
        static OnDestroyActionCallback CreateOnDestroyActionCallback(
            bool(T::*func)(), T* object)
        {
            return std::bind(func, object);
        }
        bool SetOnDestroyActionCallback(OnDestroyActionCallback callback);

        typedef std::function<bool(IPropertyPanelEventArgs* pArgs)> OnPropertyPanelEventCallback;
        template<typename T>
        static OnPropertyPanelEventCallback CreateOnPropertyPanelEventCallback(
            bool(T::*func)(IPropertyPanelEventArgs* pArgs), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnPropertyPanelEventCallback(OnPropertyPanelEventCallback callback);

        typedef std::function<bool(IUiView* pCurrentView)> OnGetFirstPointCallback;
        template<typename T>
        static OnGetFirstPointCallback CreateOnGetFirstPointCallback(
            bool(T::*func)(IUiView* pCurrentView), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnGetFirstPointCallback(OnGetFirstPointCallback callback);

        typedef std::function<bool(IUiView* pCurrentView)> OnGetCornerPointCallback;
        template<typename T>
        static OnGetCornerPointCallback CreateOnGetCornerPointCallback(
            bool(T::*func)(IUiView* pCurrentView), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnGetCornerPointCallback(OnGetCornerPointCallback callback);

        typedef std::function<bool(IUiView* pCurrentView, const Vector3d& firstPt, const Vector3d& cornerPt)> OnFinishCallback;
        template<typename T>
        static OnFinishCallback CreateOnFinishCallback(
            bool(T::*func)(IUiView* pCurrentView, const Vector3d& firstPt, const Vector3d& cornerPt), T* object)
        {
            return std::bind(func, object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
        }
        bool SetOnFinishCallback(OnFinishCallback callback);

        typedef std::function<bool(IUiView* pCurrentView, const Vector3d& firstPt, const Vector3d& pos, OwnerPtr<IGraphicsElementShape>& opPreviewGraphics)> OnPreviewCallback;
        template<typename T>
        static OnPreviewCallback CreateOnPreviewCallback(
            bool(T::*func)(IUiView* pCurrentView, const Vector3d& firstPt, const Vector3d& pos, OwnerPtr<IGraphicsElementShape>& opPreviewGraphics), T* object)
        {
            return std::bind(func, object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
        }
        bool SetOnPreviewCallback(OnPreviewCallback callback);

        // 定义输入对话框的标题和控件，如果不定义该回调函数则不弹出输入对话框
        typedef std::function<bool(DefineInputDialogParams& inputItems)> DefineInputDialogCallback;
        template<typename T>
        static DefineInputDialogCallback CreateDefineInputDialogCallback(
            bool(T::*func)(DefineInputDialogParams& inputItems), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetDefineInputDialogCallback(DefineInputDialogCallback callback);

        // 响应交互输入变化
        typedef std::function<bool(gcmp::IActionInputEventArgs* pArgs)> OnActionInputEventCallback;
        template<typename T>
        static OnActionInputEventCallback CreateOnActionInputEventCallback(
            bool(T::*func)(gcmp::IActionInputEventArgs* pArgs), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnActionInputEventCallback(OnActionInputEventCallback callback);

    protected:
        virtual bool DefinePromptMsg(std::wstring& promptMsg, const DrawRectStatus drs) override;
        virtual bool DefineCursorType(CursorType& cursorType, const DrawRectStatus drs) override;
        virtual bool DefineInputDialog(std::wstring& title, std::vector<OwnerPtr<IControlDefinition>>& inputItems) override;

    private:
        virtual bool OnInitAction(IUiView* pCurrentView) override final;
        virtual bool OnDestroyAction() override final;
        virtual bool OnActionInputEvent(gcmp::IActionInputEventArgs* pArgs) override final;
        virtual bool OnPropertyPanelEvent(IPropertyPanelEventArgs* pArgs) override final;
        virtual bool OnEnterGettingFirstPointState(IUiView* pCurrentView) override final;
        virtual bool OnEnterGettingCornerPointState(IUiView* pCurrentView) override final;
        virtual bool OnDrawRectFinished(IUiView* pCurrentView, const Vector3d& firstPt, const Vector3d& cornerPt, const ISnap* firstSnap, const ISnap* cornerSnap) override final;
        virtual bool GetGElementShapeOnPointUpdate(IUiView* pCurrentView, const Vector3d& firstPt, const Vector3d& pos, OwnerPtr<IGraphicsElementShape>& opGElementShape) override final;

    protected:
        IDocument* m_pDoc;
        OnInitActionCallback m_onInitActionCallback;
        OnDestroyActionCallback m_onDestroyActionCallback;
        OnPropertyPanelEventCallback m_onPropertyPanelEventCallback;
        OnGetFirstPointCallback m_onGetFirstPointCallback;
        OnGetCornerPointCallback m_onGetCornerPointCallback;
        OnFinishCallback m_onFinishCallback;
        OnPreviewCallback m_onPreviewCallback;
        DefineInputDialogCallback m_defineInputDialogCallback;
        OnActionInputEventCallback m_onActionInputEventCallback;
    };
}
